/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.service.knowledge;

import cn.ac.nercis.pes.common.constant.knowledge.TargetDeepness;
import cn.ac.nercis.pes.common.constant.knowledge.TargetLevel;
import cn.ac.nercis.pes.model.dto.common.Result;
import cn.ac.nercis.pes.model.dto.common.ResultCode;
import cn.ac.nercis.pes.model.dto.knowledge.KmSimpleTargetDTO;
import cn.ac.nercis.pes.model.dto.knowledge.KmUnitTargetDTO;
import cn.ac.nercis.pes.repository.dal.knowledge.KmTargetRepository;
import cn.ac.nercis.pes.repository.mapper.knowledge.KmTargetMapper;
import cn.ac.nercis.pes.repository.model.knowledge.KmTargetDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 测评指标（知识库）服务
 *
 * @author limy
 * @version 1.0.0
 */
@Slf4j
@Service
public record KmTargetService(KmTargetRepository kmTargetRepository) {
    @Autowired
    public KmTargetService {
    }

    public List<KmSimpleTargetDTO> findUnitTargets(String layerTargetName, TargetLevel level){
        var layerTarget = this.kmTargetRepository.findAllByDeepness(TargetDeepness.LAYER.getDeepness())
                .stream()
                .filter(kt->kt.getLevel()==level && StringUtils.equals(kt.getName(),layerTargetName))
                .findFirst()
                .orElse(null);
        if (Objects.isNull(layerTarget)) {
            return Collections.emptyList();
        }
        return this.kmTargetRepository.findAllByParentId(layerTarget.getId())
                .stream()
                .sorted(Comparator.comparingInt(KmTargetDO::getSort))
                .map(KmTargetMapper.INSTANCE::toSimpleTargetDTO)
                .toList();
    }

    public List<KmUnitTargetDTO> findKmTarget(String layerTargetName, TargetLevel level) {
        var targets = this.kmTargetRepository.findAllByLevel(level);
        var layerTarget = targets.stream().filter(kt -> StringUtils.equals(kt.getName(), layerTargetName))
                .findFirst()
                .orElse(null);
        if (Objects.isNull(layerTarget)) {
            return Collections.emptyList();
        }
        return targets.stream()
                .filter(ut -> StringUtils.equals(ut.getParentId(), layerTarget.getId()))
                .sorted(Comparator.comparingInt(KmTargetDO::getSort))
                .map(KmTargetMapper.INSTANCE::toDTO)
                .peek(kt -> {
                    kt.setUnitTargetId(kt.getId());
                    kt.setContent(getContentByParentId(kt.getId(), targets));
                })
                .toList();

    }

    public String getContentByParentId(String parentTargetId, List<KmTargetDO> targetDOS) {
        return targetDOS.stream()
                .filter(t -> StringUtils.equals(t.getParentId(), parentTargetId))
                .map(KmTargetDO::getName)
                .findFirst()
                .orElse("");

    }

    public Result<String> batchKmTarget(List<KmUnitTargetDTO> data) {
        Result<String> result = Result.success();
        for (var item : data) {
            result = saveKmTarget(item);
            if (!result.isSuccess()) {
                break;
            }
        }
        return result;
    }

    public Result<String> saveKmTarget(KmUnitTargetDTO kmTarget) {
        try {
            return modify(kmTarget);
        } catch (Exception e) {
            log.error("保存测评指标（知识库）信息出错：", e);
            return Result.failed();
        }
    }

    private Result<String> modify(KmUnitTargetDTO kmTarget) {
        var source = this.kmTargetRepository.findById(kmTarget.getId()).orElse(null);
        if (Objects.isNull(source)) {
            return Result.failed(ResultCode.NOT_FOUND);
        }
        source.setScore(kmTarget.getScore());
        source.setModifyTime(LocalDateTime.now());
        return Optional.of(kmTargetRepository.save(source))
                .map(KmTargetDO::getId)
                .map(Result::success)
                .orElse(Result.failed(ResultCode.FAIL));
    }

    public Result<Integer> findUnitWeight(String layerTargetName, TargetLevel level) {
        var layerTarget = this.kmTargetRepository.findAllByDeepness(TargetDeepness.LAYER.getDeepness())
                .stream()
                .filter(kt->StringUtils.equals(kt.getName(), layerTargetName) && kt.getLevel() == level)
                .findFirst()
                .orElse(null);
        if (Objects.isNull(layerTarget)) {
            return Result.failed(ResultCode.NOT_FOUND);
        }
        return Result.success(layerTarget.getWeight());
    }

    public Result<String> saveKmWeight(Integer weight, String layerTargetName, TargetLevel level) {
        var layerTarget = this.kmTargetRepository.findAllByDeepness(TargetDeepness.LAYER.getDeepness())
                .stream()
                .filter(kt->StringUtils.equals(kt.getName(), layerTargetName) && kt.getLevel() == level)
                .findFirst()
                .orElse(null);
        if (Objects.isNull(layerTarget)) {
            return Result.failed(ResultCode.NOT_FOUND);
        }
        layerTarget.setWeight(weight);
        return Optional.of(kmTargetRepository.save(layerTarget))
                .map(KmTargetDO::getId)
                .map(Result::success)
                .orElse(Result.failed(ResultCode.FAIL));
    }
}